<?php
namespace Taobao;

use Cache\Redis as cache;

/**
 * @todo api version should be update automatic from localstorage unitinfo version
 * http://h5.m.taobao.com/js/mtop/unit/.+version+./unitApi.js
 */
class TbUrlBuilder
{
    protected $order_list_url = 'https://unsz.api.m.taobao.com/h5/mtop.order.queryboughtlist/3.0/';

    protected $order_detail_url = 'https://unsz.api.m.taobao.com/h5/mtop.order.querydetail/3.0/';

    protected $logistics_url = 'https://api.m.taobao.com/h5/mtop.logistic.getlogisticbyorderid/1.0/';

    /**
     * basically is same as logistics_url
     *
     * @var string
     */
    protected $logistics_detail_url = 'https://api.m.taobao.com/h5/mtop.cnwireless.cnlogisticdetailservice.querylogisdetailbytradeid/1.0/';

    const APP_KEY = '12574478';

    const CALL_BACK_STR = 'mtopjsonp1';

    const TOKEN_KEY = '_m_h5_tk';

    protected $channel = 'taobao';

    public $timestamp;

    public $cookie_str;

    public function __construct($cookie_str = null)
    {
        $this->cookie_str = $cookie_str;
    }

    /**
     * isSessionExpired
     *
     * @param  string  $str
     * @return boolean true === expired | false === valid
     */
    public function isSessionExpired($str)
    {
        return stripos($str, 'FAIL_SYS_SESSION_EXPIRED') !== false;
    }

    /**
     * create request sign
     *
     * @param array $data
     * @return array
     * @see mtb.js
     */
    protected function createSign(array $data, $token = null)
    {
        // var TOKEN_KEY = '_m_h5_tk'; find this from mtb js
        // options.token = options.token || readCookie(TOKEN_KEY);
        // if (options.token) {
        //     options.token = options.token.split('_')[0];
        // }
        // var TOKEN_ENC_KEY = '_m_h5_tk_enc'; another key currently don't know what is it
        // sequence:token,timestamp,appkey,data
        if(!$token){
            $token = $this->getToken();
        }
        $data = json_encode($data, JSON_UNESCAPED_UNICODE);
        return  md5(implode('&', [$token, $this->getTimeStamp(), static::APP_KEY, $data]));
    }

    /**
     * get token from cookie string
     *
     * before _ is the token,after _ is the token expires time
     *
     * @param  boolean $renew
     * @return string
     */
    protected function getToken($renew = false)
    {
        $key = '';
        if($renew || !($token = cache::get($key))){
            $tokens = $this->findInfoFromCookieStr(static::TOKEN_KEY);
            list($token, $expires_time) = explode('_', $tokens);
            $ttl = floor($expires_time/1000) - time();
            if(is_int($ttl) && $ttl >= 300){
                cache::set($key, $token, $ttl);
            }
        }
        return $token;
    }

    /**
     * findInfoFromCookieStr
     *
     * @param  string $tag
     * @param  string|null $cookies
     * @return string
     */
    public function findInfoFromCookieStr($tag, $cookies = null)
    {
        $result = '';
        if (!$tag || !is_string($tag)) {
            return $result;
        }
        if ($cookies === null) {
            $cookies = $this->cookie_str;
        }
        if ($cookies) {
            $cookies = "; " . $cookies . '; ';
            $pattern = '/(?:;\s)(?:' . preg_quote(trim($tag)) . '=)([^;]*)(?:;\s)/';
            if (preg_match($pattern, $cookies, $match)) {
                $result = $match[1];
            }
        }
        return $result;
    }

    /**
     * getTimeStamp
     *
     * @return integer
     */
    protected function getTimeStamp()
    {
        if(!$this->timestamp){
            $time = microtime(true);
            $this->timestamp = floor($time * 1000);
        }
        return $this->timestamp;
    }

    /**
     * jsonpPreProcessor
     *
     * @param  string $str
     * @param  string $callback
     * @return array|null
     */
    private function jsonpPreProcessor($str, $callback = self::CALL_BACK_STR)
    {
        $str = trim(preg_replace('/^'.$callback.'(/', '', $str), '');
        $arr = json_decode($str, true);
        return json_last_error() === JSON_ERROR_NONE ? $arr : null;
    }

    /**
     * buildRequestUrl
     *
     * @return string
     * @see order.js
     */
    public function buildQueryBoughtListUrl($page = 1)
    {
        $data = [
            'page' => $page,
            // 'tabCode' => 'all',
            'tabCode' => 'waitConfirm',
            'appVersion' => '1.0',
            'appName' => 'tborder',
        ];
        $params = [
            'appKey' => static::APP_KEY,
            't' => $this->getTimeStamp(),
            'sign' => $this->createSign($data),
            'api' => 'mtop.order.queryBoughtList',
            'v' => '3.0',
            'ttid' => '##h5',
            'ecode' => '1',
            'AntiFlood' => 'true',
            'AntiCreep' => 'true',
            'LoginRequest' => 'true',
            'type' => 'jsonp',
            'dataType' => 'jsonp',
            'callback' => self::CALL_BACK_STR,
            'data' => json_encode($data),
        ];
        return $this->order_list_url.'?'.http_build_query($params);
    }

    /**
     * buildQueryOrderDetailUrl
     *
     * @param  string $oid
     * @return string
     */
    public function buildQueryOrderDetailUrl($oid)
    {
        $conditions = [
                'extra' => [
                    'attributes' => new \stdClass()
                ]
            ];
        $data = [
            'bizOrderId' => $oid,
            'archive' => 'false',
            'appVersion' => '1.0',
            'appName' => 'tborder',
            // 'spm' => 'a2141.7631731.0.i1',  //???
            'condition' => json_encode($conditions)
        ];

        $params = [
            'appKey' => static::APP_KEY,
            't' => $this->getTimeStamp(),
            'sign' => $this->createSign($data),
            'api' => 'mtop.order.queryDetail',
            'v' => '3.0',
            'ttid' => '##h5',
            'ecode' => '1',
            'AntiFlood' => 'true',
            'AntiCreep' => 'true',
            'LoginRequest' => 'true',
            'type' => 'jsonp',
            'dataType' => 'jsonp',
            'callback' => self::CALL_BACK_STR,
            'data' => json_encode($data),
        ];
        return $this->order_detail_url.'?'.http_build_query($params);
    }

    /**
     * buildQueryLogisticsUrl
     *
     * pass an orderid to build request url
     *
     * @param  integer|string $oid
     * @return string
     */
    public function buildQueryLogisticsUrl($oid)
    {
        $data = [
            'orderId' => $oid
        ];
        $params = [
            'appKey' => static::APP_KEY,
            't' => $this->getTimeStamp(),
            'sign' => $this->createSign($data),
            'api' => 'mtop.logistic.getLogisticByOrderId',
            'v' => '1.0',
            'type' => 'jsonp',
            'callback' => self::CALL_BACK_STR,
            'data' => json_encode($data),
        ];
        return $this->logistics_url.'?'.http_build_query($params);
    }

    /**
     * buildLogisDetailByWaybillUrl
     *
     * basically is same as buildQueryLogisticsUrl
     *
     * @param  string $oid
     * @return string
     */
    public function buildLogisDetailByWaybillUrl($oid)
    {
        $data = [
            'orderId' => $oid
        ];
        $params = [
            'appKey' => static::APP_KEY,
            't' => $this->getTimeStamp(),
            'sign' => $this->createSign($data),
            'api' => 'mtop.cnwireless.CNLogisticDetailService.queryLogisDetailByTradeId',
            'v' => '1.0',
            'ecode' => 1,
            'LoginRequest' => 'true',
            'type' => 'jsonp',
            'dataType' => 'jsonp',
            'callback' => self::CALL_BACK_STR,
            'data' => json_encode($data),
        ];
        return $this->logistics_detail_url.'?'.http_build_query($params);
    }
}


$token = '327632f50ffe659225367e9f3a1bcd42';
$time = '1476670636246';
$key = '12574478';
$data = [
    'orderId' => '2411405283833893',
];


// $data = json_encode($data);

// echo md5(implode('&', [$token, $time, $key, $data]));

// date_default_timezone_set('PRC');

// 1476433856008
// 1476428266873
// echo date('Y-m-d H:i:s', floor(1476433856008/1000));
// $conditions = [
//         'extra' => [
//             'attributes' => new \stdClass()
//         ]
//     ];
// $data = [
//     'bizOrderId' => 123,
//     'archive' => 'false',
//     'appVersion' => '1.0',
//     'appName' => 'tborder',
//     'spm' => 'a2141.7631731.0.i1',  //???
//     'condition' => json_encode($conditions)
// ];
// data:{"bizOrderId":"2376261101403893","archive":"false","spm":"a2141.7631731.0.i1","appName":"tborder","appVersion":"1.0","condition":"{\"extra\":{\"attributes\":{}}}"}
// echo json_encode($data);
